<!--
 *商品列表管理，分类参数页面
 *需要完善：表格合并,动态参数/静态参数的添加，修改事件合并
 * @Author: 舒克
 * @Official Accounts: 氧化1028
 * @email: 143587623@qq.com
 * @github: https://gitee.com/KingSio
 * @Date: 2021-02-15 23:39:14
 * @LastEditTime: 2021-02-22 18:25:41
 * @FilePath: \Vue全栈后台\项目\vue_shop\src\components\goods\Params.vue
-->
<template>
  <div>
    <!-- 卡片视图区域 -->
    <el-card>
      <!-- 警告区域 -->
      <el-alert
        title="注意：只允许为第三级分类设置相关参数！"
        type="warning"
        show-icon
        :closable="false"
      ></el-alert>

      <!-- 选择商品分类区域 -->
      <el-row class="cat_opt">
        <el-col>
          <span>选择商品分类：</span>
          <!-- 商品分类的级联选择框 -->
          <el-cascader
            v-model="selectedCateKeys"
            :options="cateList"
            :props="cateProps"
            @change="handleChange"
          ></el-cascader>
        </el-col>
      </el-row>

      <!-- tab页区域 -->
      <el-tabs v-model="activeTabsName" @tab-click="handleTabClick">
        <!-- 添加动态参数 many(定义接口传参的一个字段，具体看接口说明)-->
        <el-tab-pane label="动态参数" name="many">
          <el-button
            type="primary"
            size="mini"
            :disabled="isBtnDisabled"
            @click="addDialogVisible = true"
            >添加动态参数</el-button
          >
          <!-- 动态参数表格 ,表格里面，如果要表格嵌套数据，  manyTableData.data数组的内容，这里最后用插槽获取-->
          <el-table :data="manyTableData" border stripe>
            <!-- 展开项 -->
            <el-table-column type="expand">
              <!-- tag标签，这里有点类似电渠项目功能 -->
              <template slot-scope="scope">
                <el-tag
                  v-for="(item, index) in scope.row.attr_vals"
                  :key="index"
                  closable
                >
                  {{ item }}
                </el-tag>
                <!-- 动态添加标签 -->
                <!-- 输入的文本框 -->
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.inputValue"
                  ref="saveTagInput"
                  size="small"
                  @keyup.enter.native="handleInputConfirm(scope.row)"
                  @blur="handleInputConfirm(scope.row)"
                >
                </el-input>
                <!-- 添加按钮 -->
                <el-button
                  v-else
                  class="button-new-tag"
                  size="small"
                  @click="showInput(scope.row)"
                  >+ 添加</el-button
                >
              </template>
            </el-table-column>

            <el-table-column type="index">#</el-table-column>
            <el-table-column
              label="参数名称"
              prop="attr_name"
            ></el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button
                  :scope="scope"
                  size="mini"
                  type="primary"
                  icon="el-icon-edit"
                  @click="showEditDialog(scope.row.attr_id)"
                  >编辑</el-button
                >
                <el-button
                  size="mini"
                  type="primary"
                  icon="el-icon-delete"
                  @click="removeParams(scope.row.attr_id)"
                  >删除</el-button
                >
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <!-- 添加静态属性的面板  only(定义接口传参的一个字段定义接口传参的一个字段，具体看接口说明)-->
        <el-tab-pane label="静态属性" name="only">
          <el-button
            type="primary"
            size="mini"
            :disabled="isBtnDisabled"
            @click="addDialogVisible = true"
            >添加静态属性</el-button
          >
          <!-- 静态参数表格 -->
          <el-table :data="onlyTableData" border stripe>
            <!-- 展开项 -->
            <el-table-column type="expand"> </el-table-column>

            <el-table-column type="index">#</el-table-column>
            <el-table-column
              label="属性名称"
              prop="attr_name"
            ></el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button
                  :scope="scope"
                  size="mini"
                  type="primary"
                  icon="el-icon-edit"
                  @click="showEditDialog(scope.row.attr_id)"
                  >编辑</el-button
                >
                <el-button
                  size="mini"
                  type="primary"
                  icon="el-icon-delete"
                  @click="removeParams(scope.row.attr_id)"
                  >删除</el-button
                >
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <!-- 对话框，添加动态、静态参数的,-->
    <el-dialog
      :title="'添加' + titleText"
      :visible.sync="addDialogVisible"
      width="30%"
      @close="addDialogClosed"
    >
      <!-- 
      添加的弹框
      prop：这里的验证规则，最好使用后端定义的字段
     -->
      <el-form
        ref="addFormRef"
        :model="addForm"
        :rules="addFormRules"
        label-width="80px"
      >
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="addForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addParams">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 编辑的弹框-->
    <el-dialog
      :title="'编辑' + titleText"
      :visible.sync="editDialogVisible"
      width="30%"
      @close="editDialogClosed"
    >
      <el-form
        ref="editFormRef"
        :model="editForm"
        :rules="editFormRules"
        label-width="80px"
      >
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="editForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editParams">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  getCategoriesListData,
  getCategoriesAttributesListData,
  postCategoriesAttributesListData,
  getEditCategoriesAttributesListData,
  putEditCategoriesAttributesListData,
  removeEditCategoriesAttributesListData
} from '@/api/commodityApi'

export default {
  data() {
    return {
      //商品分类列表
      cateList: [],
      //   级联选择框的配置对象
      cateProps: {
        expandTrigger: 'hover',
        value: 'cat_id',
        label: 'cat_name',
        children: 'children'
      },
      //选择分类，级连选择框,双向绑定的数组
      selectedCateKeys: [],
      //被激活页签名称
      activeTabsName: 'many',
      //动态数据
      manyTableData: [],
      //静态数据
      onlyTableData: [],

      //添加的弹框，控制它显示，隐藏
      addDialogVisible: false,
      //添加弹框的，表单数据
      addForm: {
        attr_name: ''
      },
      //添加的弹框，验证规则
      addFormRules: {
        attr_name: [
          { required: true, message: '请输入参数名称', trigger: 'blur' }
        ]
      },

      //编辑的弹框显示隐藏
      editDialogVisible: false,
      //编辑表单的字段
      editForm: {
        attr_name: ''
      },
      editFormRules: {
        attr_name: [
          { required: true, message: '请输入参数名称', trigger: 'blur' }
        ]
      },
    }
  },
  created() {
    this.getCateList()
  },
  computed: {
    //如果按钮被禁用，则返回true，否则返回false
    isBtnDisabled() {
      //不等于3，表示用户还没有选择
      if (this.selectedCateKeys.length !== 3) {
        return true
      } else {
        return false
      }
    },

    //当前选择的id
    getCateId() {
      if (this.selectedCateKeys.length === 3) {
        return this.selectedCateKeys[2] //选择2，因为数组存放三个字段id，0，1，2（最后一位是三级分类的id）
      } else {
        return null
      }
    },

    //共用一个添加对话框，头部文本变量
    titleText() {
      if (this.activeTabsName == 'many') {
        return '动态参数'
      } else {
        return '静态参数'
      }
    }
  },
  methods: {
    async getCateList() {
      const { data: res } = await getCategoriesListData()
      if (res.meta.status !== 200) {
        return this.$message.error('获取商品分类失败')
      }
      console.log(res.data)
      this.cateList = res.data
    },
    // 级联选择框 选中变化 触发
    handleChange() {
      this.getParamsData()
    },
    //选择分类事件，选择级连选择框的数据
    async getParamsData() {
      //这里只能选择三级分类，好像饿了么不加change-on-select，只能选择三级，其它都不能选择
      if (this.selectedCateKeys.length !== 3) {
        //表示选择了其它级别
        this.selectedCateKeys = [] //清空选择的输入框
        return
      }

      console.log(this.selectedCateKeys)
      //如果选择了三级分类
      //就根据选择的id，去获取对应的数据
      let params = {
        sel: this.activeTabsName
      }
      const { data: res } = await getCategoriesAttributesListData(
        this.getCateId,
        params
      )
      if (res.meta.status !== 200) {
        return this.$message.error('获取参数列表失败')
      }

      //获取每一个分类下的说明
      /* 
      attr_vals: "49吋4K超薄曲面 人工智能,55吋4K观影曲面
      这里是空格，隔开的字符串，需要切割成数组，split
      这里要增加一个判断，如果该分类是新添加，
      "".split(" ")会返回[""]，页面会渲染一个没有数据标签
      那么直接返回一个null，或者[]

      */
     console.log(res.data)
      res.data.forEach(item => {
        //这里如果为空需要返回一个数组，如果为nul表示基本数据类型，定义数组是因为后面pus的是一个
        item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
        //为每一项，添加一个控制文本输入框的显示隐藏
        //那么就可以确定，具体是哪一项显示
        item.inputVisible=false
        //并且文本输入框的内容默认为空
        item.inputValue=""
      })

      //判断获取到的属于那一部分的数据
      if (this.activeTabsName == 'many') {
        this.manyTableData = res.data
      } else {
        this.onlyTableData = res.data
      }
    },

    //tab页签点击事件的处理函数
    handleTabClick() {
      /* this.activeTabsName，是根据动态参数，还是静态参数的值 */
      this.getParamsData() //点击切换tab标签页的时候再次发起请求
    },

    //添加弹框的，关闭事件
    addDialogClosed() {
      this.$refs.addFormRef.resetFields()
    },

    //添加弹框，提交事件
    addParams() {
      this.$refs.addFormRef.validate(async val => {
        let params = {
          attr_name: this.addForm.attr_name, //添加的名v
          attr_sel: this.activeTabsName //添加动态的属性，还是静态的属性数据（many或者only）
        }
        if (!val) return
        const { data: res } = await postCategoriesAttributesListData(
          this.getCateId,
          params
        )

        if (res.meta.status !== 201) {
          return this.$message.error('添加参数失败')
        }
        this.$message.success('添加参数成功')
        this.addDialogVisible = false
        this.getParamsData() //重新获取，刷新数据
      })
    },

    //编辑事件，打开对话框
    async showEditDialog(attrId) {
      let params = {
        //动态数据、静态数据
        attr_sel: this.activeTabsName
      }
      //参数1，分类id,参数2：具体修改那个的id
      const { data: res } = await getEditCategoriesAttributesListData(
        this.getCateId,
        attrId,
        params
      )
      if (res.meta.status !== 200) {
        return this.$message.error('获取失败')
      }
      console.log(res.data)
      this.editForm = res.data
      this.editDialogVisible = true
    },
    //编辑事件，关闭对话框，清空对话框
    editDialogClosed() {
      this.$refs.editFormRef.resetFields()
    },

    //编辑事件，提交
    async editParams() {
      let params = {
        attr_name: this.editForm.attr_name, //修改后的数据
        attr_sel: this.editForm.attr_sel //属性的类型[many或only]
      }

      const { data: res } = await putEditCategoriesAttributesListData(
        this.getCateId,
        this.editForm.attr_id,
        params
      )
      if (res.meta.status !== 200) {
        return this.$message.error('修改失败')
      }
      this.getParamsData() //刷新数据
      this.$message.success('修改成功')
      this.editDialogVisible = false
    },

    //删除事件
    async removeParams(attr_id) {
      const confirmRes = await this.$confirm(
        '此操作将永久删除该文件, 是否继续?',
        '提示',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).catch(error => {
        error
      })

      if (confirmRes !== 'confirm') {
        return this.$message({
          type: 'info',
          message: '已取消删除'
        })
      }
      //Params:参数1是分类id,attr_id是具体删除的id
      const { data: res } = await removeEditCategoriesAttributesListData(
        this.getCateId,
        attr_id
      )
      if (res.meta.status !== 200) {
        return this.$message.error('删除失败')
      }
      this.$message.success('删除成功')
      this.getParamsData() //刷新数据
    },

    //文本框失去焦点（点击输入框以外的地方），或者按下回车
   async handleInputConfirm(row){
      //清除空格再计算，因为空格也算长度
      if(row.inputValue.trim().length===0){
          row.inputValue=""  
          row.inputVisible=false;//隐藏输入框
          return
      }
      //因为需要拿到attr_vals整个字段，所以这里要push到这个接口字段中
      row.attr_vals.push(row.inputValue.trim())
      row.inputValue="";
      row.inputVisible=false;//隐藏输入框
      
      //接口请求体参数
       let params = {
        attr_name: row.attr_name, //修改后的数据
        attr_sel: row.attr_sel, //属性的类型[many或only]
        attr_vals: row.attr_vals.join(" ")//因为这里attr_vals是数组，后端这里接受字符串，需要把数组转换为字符串
        //attr_vals:row.inputValue
        //这里是编辑接口，
        //问题：attr_vals:row.inputValue，直接把输入框的内容给后端
        //导致：每次请求后，覆盖原来的内容，
        //因为：本地这个tag标签的内容是一整个字符串，只获取输入框的内容，会覆盖，所以要push到这个数组里面，
        //然后切割成功字符串获取整个的数组内容
        //解决：需要把全部的内容都发到后端，包括原来的，新编辑的
    }
    
      const { data: res } = await putEditCategoriesAttributesListData(
        this.getCateId,//分类id
        row.attr_id,//修改分类尝参数的参数id
        params  //请求体内容
      )
      if (res.meta.status !== 200) {
        return this.$message.error('添加参数项失败')
      }  
      //这里重新请求，会导致整个表格刷新，应该不使用重新请求
      //this.getParamsData() //刷新数据

      //row.attr_vals.push(res.data.attr_vals)
      this.$message.success('添加成功')
     

   },
    //点击添加，显示添加标签的输入框
    showInput(row){
        row.inputVisible=true
        //自动获取焦点，就是光标
        /* $nextTick的作用
        就是当页面元素重新渲染之后，才指定回调函数中的代码
        比如这里，点击显示输入框后，但是还没重新渲染就执行this.$refs.saveTagInput.$refs.input.focus()
        是获取不到的，需要等待渲染结束，才可以拿到最新的DOM
        */
        this.$nextTick(()=>{
          this.$refs.saveTagInput.$refs.input.focus()
        })
     }
  }
}
</script>
<style lang="less" scoped>
.cat_opt {
  margin-top: 20px;
}
.el-tag {
  margin: 10px;
}
.input-new-tag{
  width: 120px;
}
</style>
